<template>
  <transition name="zoom-in-bottom" @after-leave="$emit('dodestroy')">
    <div
      v-show="visible"
      :style="{width: width}"
      class="picker-panel date-picker"
      :class="[{
        'has-sidebar': $slots.sidebar || shortcuts,
        'has-time': showTime
      }]">
      <div class="picker-panel__body-wrapper">
        <slot name="sidebar" class="picker-panel__sidebar"></slot>
        <div class="picker-panel__sidebar" v-if="shortcuts">
          <button
            type="button"
            class="picker-panel__shortcut"
            v-for="shortcut in shortcuts"
            @click="handleShortcutClick(shortcut)">{{ shortcut.text }}</button>
        </div>
        <div class="picker-panel__body">
          <div class="date-picker__time-header" v-if="showTime">
            <span class="date-picker__editor-wrap">
              <input class="form-control" :placeholder="getLocale('datePicker.selectDate')"
                     :value="visibleDate"
                     @input.de="visibleDate = $event">
            </span>
            <span class="date-picker__editor-wrap">
              <input class="form-control" ref="input" v-show="false"
                     :placeholder="getLocale('datePicker.selectTime')"
                     :value="visibleTime"
                     @focus="timePickerVisible = !timePickerVisible"
                     @input="visibleTime = $event">
              <time-picker
                ref="timepicker"
                :date="date"
                :visible="true"
                @pick="handleTimePick"
                @mounted="$refs.timepicker.format=timeFormat">
              </time-picker>
            </span>
          </div>
          <div class="date-picker__header" v-show="currentView !== 'time'">
            <button
              type="button"
              @click="prevYear"
              class="picker-panel__icon-btn date-picker__prev-btn icon-d-arrow-left">
            </button>
            <button
              type="button"
              @click="prevMonth"
              v-show="currentView === 'date'"
              class="picker-panel__icon-btn date-picker__prev-btn icon-arrow-left">
            </button>
            <span
              @click="showYearPicker"
              class="date-picker__header-label">{{yearLabel}}</span>
            <span
              @click="showMonthPicker"
              v-show="currentView === 'date' || currentView === 'pickTime'"
              class="date-picker__header-label"
              :class="{ active: currentView === 'month' }">{{monthLabel}}</span>
            <button
              type="button"
              @click="nextYear"
              class="picker-panel__icon-btn date-picker__next-btn icon-d-arrow-right">
            </button>
            <button
              type="button"
              @click="nextMonth"
              v-show="currentView === 'date'"
              class="picker-panel__icon-btn date-picker__next-btn icon-arrow-right">
            </button>
          </div>

          <div class="picker-panel__content">
            <date-table
              v-show="currentView === 'date'"
              @pick="handleDatePick"
              :year="year"
              :month="month"
              :date="date"
              :week="week"
              :selection-mode="selectionMode"
              :first-day-of-week="firstDayOfWeek"
              :disabled-date="disabledDate">
            </date-table>
            <year-table
              ref="yearTable"
              :year="year"
              :date="date"
              v-show="currentView === 'year'"
              @pick="handleYearPick"
              :disabled-date="disabledDate">
            </year-table>
            <month-table
              :month="month"
              :date="date"
              v-show="currentView === 'month'"
              @pick="handleMonthPick"
              :disabled-date="disabledDate">
            </month-table>
          </div>
        </div>
      </div>

      <div
        class="picker-panel__footer"
        v-show="footerVisible">
        <a
          class="picker-panel__link-btn"
          @click="changeToNow">{{ getLocale('datePicker.now') }}</a>
        <a v-if="clearable"
          class="picker-panel__link-btn"
          @click="handleClear">{{ getLocale('datePicker.clear') }}</a>
        <button v-if="showTime"
          type="button"
          class="picker-panel__btn"
          @click="confirm">{{ getLocale('datePicker.confirm') }}</button>
      </div>
    </div>
  </transition>
</template>

<script type="text/babel">
  import {DateUtils} from '../utils'
  import TimePicker from './time.vue'
  import YearTable from '../basic/year-table.vue'
  import MonthTable from '../basic/month-table.vue'
  import DateTable from '../basic/date-table.vue'
  import LOCALES from '../../../locales'

  export default {
    components: {
      TimePicker, YearTable, MonthTable, DateTable
    },

    watch: {
      showTime (val) {
        /* istanbul ignore if */
        if (!val) return
        this.$nextTick(() => {
          if (this.$refs.input) {
            this.pickerWidth = this.$refs.input.getBoundingClientRect().width + 10
          }
        })
      },

      value (newVal) {
        if (!newVal) return
        newVal = new Date(newVal)
        if (!isNaN(newVal)) {
          if (typeof this.disabledDate === 'function' &&
            this.disabledDate(new Date(newVal))) {
            return
          }
          this.date = newVal
          this.year = newVal.getFullYear()
          this.month = newVal.getMonth()
          this.$emit('pick', newVal, false)
        }
      },

      selectionMode (newVal) {
        if (newVal === 'month') {
          /* istanbul ignore next */
          if (this.currentView !== 'year' || this.currentView !== 'month') {
            this.currentView = 'month'
          }
        } else if (newVal === 'week') {
          this.week = DateUtils.getWeekNumber(this.date)
        }
      },

      date (newVal) {
        this.year = newVal.getFullYear()
        this.month = newVal.getMonth()
        if (this.selectionMode === 'week') this.week = DateUtils.getWeekNumber(newVal)
      }
    },

    methods: {

      getLocale: LOCALES.GetLocale,

      handleClear () {
        this.date = this.defaultValue ? new Date(this.defaultValue) : new Date()
        this.$emit('pick')
      },

      resetDate () {
        this.date = new Date(this.date)
      },

      showMonthPicker () {
        this.currentView = 'month'
      },

      showYearPicker () {
        this.currentView = 'year'
      },

      // XXX: 没用到
      // handleLabelClick () {
      //   if (this.currentView === 'date') {
      //     this.showMonthPicker()
      //   } else if (this.currentView === 'month') {
      //     this.showYearPicker()
      //   }
      // },

      prevMonth () {
        this.month--
        if (this.month < 0) {
          this.month = 11
          this.year--
        }
      },

      nextMonth () {
        this.month++
        if (this.month > 11) {
          this.month = 0
          this.year++
        }
      },

      nextYear () {
        if (this.currentView === 'year') {
          this.$refs.yearTable.nextTenYear()
        } else {
          this.year++
          this.date.setFullYear(this.year)
          this.resetDate()
        }
      },

      prevYear () {
        if (this.currentView === 'year') {
          this.$refs.yearTable.prevTenYear()
        } else {
          this.year--
          this.date.setFullYear(this.year)
          this.resetDate()
        }
      },

      handleShortcutClick (shortcut) {
        if (shortcut.onClick) {
          shortcut.onClick(this)
        }
      },

      handleTimePick (picker, visible, first) {
        if (picker) {
          let oldDate = new Date(this.date.getTime())
          let hour = picker.getHours()
          let minute = picker.getMinutes()
          let second = picker.getSeconds()
          oldDate.setHours(hour)
          oldDate.setMinutes(minute)
          oldDate.setSeconds(second)
          this.date = new Date(oldDate.getTime())
        }

        if (!first) {
          this.timePickerVisible = visible
        }
      },

      handleMonthPick (month) {
        this.month = month
        const selectionMode = this.selectionMode
        if (selectionMode !== 'month') {
          this.date.setMonth(month)
          this.currentView = 'date'
          this.resetDate()
        } else {
          this.date.setMonth(month)
          this.year && this.date.setFullYear(this.year)
          this.resetDate()
          const value = new Date(this.date.getFullYear(), month, 1)
          this.$emit('pick', value)
        }
      },

      handleDatePick (value) {
        if (this.selectionMode === 'day') {
          if (!this.showTime) {
            this.$emit('pick', new Date(value.getTime()))
          }
          this.date.setFullYear(value.getFullYear())
          this.date.setMonth(value.getMonth(), value.getDate())
        } else if (this.selectionMode === 'week') {
          this.week = value.week
          this.$emit('pick', value.date)
        }

        this.resetDate()
      },

      handleYearPick (year, close = true) {
        this.year = year
        if (!close) return

        this.date.setFullYear(year)
        if (this.selectionMode === 'year') {
          this.$emit('pick', new Date(year, 0, 1))
        } else {
          this.currentView = 'month'
        }

        this.resetDate()
      },

      changeToNow () {
        this.date.setTime(+new Date())
        this.$emit('pick', new Date(this.date.getTime()))
        this.resetDate()
      },

      confirm () {
        this.$emit('pick', this.date)
      },

      resetView () {
        if (this.selectionMode === 'month') {
          this.currentView = 'month'
        } else if (this.selectionMode === 'year') {
          this.currentView = 'year'
        } else {
          this.currentView = 'date'
        }

        if (this.selectionMode !== 'week') {
          this.year = this.date.getFullYear()
          this.month = this.date.getMonth()
        }
      }
    },

    mounted () {
      if (this.date && !this.year) {
        this.year = this.date.getFullYear()
        this.month = this.date.getMonth()
      }
    },

    data () {
      return {
        pickerWidth: 0,
        date: this.defaultValue ? new Date(this.defaultValue) : new Date(),
        value: '',
        showTime: false,
        selectionMode: 'day',
        shortcuts: '',
        visible: false,
        currentView: 'date',
        disabledDate: '',
        firstDayOfWeek: 7,
        year: null,
        month: null,
        week: null,
        showWeekNumber: false,
        timePickerVisible: false,
        format: '',
        width: 0,
        defaultValue: '',
        clearable: true
      }
    },

    computed: {
      monthLabel () {
        return this.getLocale(`datePicker.months.${DateUtils.MONTHS[this.month]}`)
      },
//
//      dateLabel () {
//        return this.date.getDate() + '日'
//      },

      footerVisible () {
        return this.showTime || this.clearable
      },

      visibleTime: {
        get () {
          return DateUtils.formatDate(this.date, this.timeFormat)
        },

        set (evt) {
          let val = evt.target.value
          if (/^(([0-1]?[0-9])|(2[0-3])):[0-5]?[0-9](:[0-5]?[0-9])?$/.test(val)) {
            const date = DateUtils.parseDate(val, this.timeFormat)
            date.setFullYear(this.date.getFullYear())
            date.setMonth(this.date.getMonth())
            date.setDate(this.date.getDate())
            this.date = date
            this.$refs.timepicker.value = date
            this.timePickerVisible = false
          } else {
            evt.target.value = DateUtils.formatDate(this.date, this.timeFormat)
          }
        }
      },

      visibleDate: {
        get () {
          return DateUtils.formatDate(this.date)
        },

        set (evt) {
          let val = evt.target.value
          const date = DateUtils.parseDate(val, 'yyyy-MM-dd')
          if (!date || (typeof this.disabledDate === 'function' && this.disabledDate(date))) {
            evt.target.value = DateUtils.formatDate(this.date, 'yyyy-MM-dd')
            return
          }
          date.setHours(this.date.getHours())
          date.setMinutes(this.date.getMinutes())
          date.setSeconds(this.date.getSeconds())
          this.date = date
          this.resetView()
        }
      },

      yearLabel () {
        const year = this.year
        if (!year) return ''
        const yearTranslation = this.getLocale('datePicker.year')
        if (this.currentView === 'year') {
          const startYear = Math.floor(year / 10) * 10
          if (yearTranslation) {
            return startYear + ' ' + yearTranslation + ' - ' + (startYear + 9) + ' ' + yearTranslation
          }
          return startYear + ' - ' + (startYear + 9)
        }
        return this.year + ' ' + yearTranslation
      },

      timeFormat () {
        if (this.format && this.format.indexOf('ss') === -1) {
          return 'HH:mm'
        } else {
          return 'HH:mm:ss'
        }
      }
    }
  }
</script>

<style lang="scss">
  @import "button";
  @import "panel";

  .date-picker {
    min-width: 254px;

    &.has-sidebar.has-time {
      min-width: 434px;
    }

    &.has-sidebar {
      min-width: 370px;
    }

    &.has-time {
      min-width: 324px;
    }

    .picker-panel__content {
      min-width: 224px;
    }

    table {
      table-layout: fixed;
      width: 100%;
    }

    .date-picker__editor-wrap {
      position: relative;
      display: table-cell;
      padding: 0 5px;
    }

    .date-picker__time-header {
      position: relative;
      border-bottom: 1px solid $datePicker-inner-border-color;
      font-size: 12px;
      padding: 8px 5px;
      display: table;
      width: 100%;
      box-sizing: border-box;

      input {
        width: 100% !important;
      }
    }

    .date-picker__header {
      padding: 0 10px;
      text-align: center;
      line-height: 40px;

      button, span{
        display: inline-block;
        vertical-align: middle;
      }
    }

    .date-picker__header-label {
      font-size: 14px;
      padding: 0 5px;
      line-height: 22px;
      text-align: center;
      cursor: pointer;

      &:hover {
        color: var(--datepicker-text-hover-color);
      }

      &.active {
        color: var(--datepicker-active-color);
      }
    }

    .date-picker__prev-btn {
      float: left;
    }

    .date-picker__next-btn {
      float: right;
    }

    .date-picker__time-wrap {
      padding: 10px;
      text-align: center;
    }

    .date-picker__time-label {
      float: left;
      cursor: pointer;
      line-height: 30px;
      margin-left: 10px;
    }
  }
</style>
